﻿using AE_BEPUPhysics_Addition;
using BEPUutilities;
using FixMath.NET;
using GameConfig;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TEngine;
using UnityEngine;
using static UnityEditor.PlayerSettings;

namespace GameLogic
{
    public class WeaponControl
    {
        WeaponView m_WeaponView;
        WeaponData m_WeaponData;
        ShipSlotControl m_SlotControl;
        BEPUutilities.Vector3 m_LocalPos;
        FireStrategy m_FireStrategy;
        public BEPUutilities.Vector3 WeaponPos
        {
            get
            {
                return m_SlotControl.GetShipPosition() + BEPUutilities.Quaternion.Transform(m_LocalPos, m_SlotControl.GetShipRotation());
            }
        }
        public UnityEngine.Vector3 ViewWeaponPos
        {
            get { 
                return m_SlotControl.GetShipControl().ShipView.SpriteRenderer.transform.position + (m_SlotControl.GetShipControl().ShipView.SpriteRenderer.transform.rotation * m_LocalPos.ToFloat());
            }
        }
        public void Clean()
        {
            PoolManager.Instance.PushGameObject(m_WeaponView.gameObject);
        }

        public WeaponData WeaponData { get => m_WeaponData; set => m_WeaponData = value; }

        public WeaponControl(int weaponID, ShipSlotControl slotControl) {
            m_SlotControl = slotControl;
            m_WeaponData = WeaponData.Create(weaponID);
            if (m_WeaponData.Cfg == null)
            {
                Debug.LogError("weapon config file is missing: " + weaponID);
                return;
            }

            var weaponObj = PoolManager.Instance.GetGameObjectCustomFlagName(m_WeaponData.GetIdentityStr(), m_SlotControl.GetShipView().SpriteRenderer.transform);
            m_WeaponView = weaponObj.GetOrAddComponent<WeaponView>();
            m_WeaponView.Init(m_WeaponData);

            var resulution = m_SlotControl.GetShipView().GetResulution();

            var x = ((m_SlotControl.SlotDesignData.PosX /1000m )* resulution.x / 2) / 100;
            var y = ((m_SlotControl.SlotDesignData.PosY / 1000m) * resulution.y / 2) / 100;
            m_LocalPos = new BEPUutilities.Vector3(x, y, 0);
            m_WeaponView.transform.localPosition = m_LocalPos.ToFloat() ;
            switch(m_WeaponData.Cfg.Type)
            {
                case GameConfig.weapon.EType.Kinetic:
                    m_FireStrategy = new LiveAmmunitionStrategy();
                    break;
                case GameConfig.weapon.EType.Missile:
                    m_FireStrategy = new LiveAmmunitionStrategy();
                    break;
                case GameConfig.weapon.EType.UAV:
                    break;
                case GameConfig.weapon.EType.Laser:
                    m_FireStrategy = new LaserStrategy();
                    break;
            }
            m_FireStrategy.Init(this, m_SlotControl);
        }
        ~WeaponControl()
        {
            PoolManager.Instance.PushGameObject(m_WeaponView.gameObject);
        }
        public void DoLogic()
        {
            m_WeaponData.ShotCoolingFrame++;
            if (m_FireStrategy != null)
                m_FireStrategy.DoLogic();
        }
        public void Update()
        {
            if (m_FireStrategy != null)
                m_FireStrategy.Update();
        }
        public void Fire()
        {
            if(m_WeaponData.ShotCoolingFrame > m_WeaponData.ShotCoolingFrameMax)
            {
                if (m_FireStrategy != null)
                    m_FireStrategy.Fire(WeaponPos);
                m_WeaponData.ShotCoolingFrame = 0;
            }
        }
        public void AimPos(BEPUutilities.Vector2 pos)
        {
            //Debug.Log("AimPos = "+pos);
            //Debug.Log("WeaponAngle = "+ WeaponData.Angle);
            //WeaponData.Angle += SystemModule.Instance.LogicDelta /10;
            //var selfRot = BEPUutilities.Quaternion.CreateFromAxisAngle(new BEPUutilities.Vector3(0, 0, -1),  MathHelper.ToDegrees(WeaponData.Angle));
            //m_WeaponView.transform.rotation = selfRot.ToFloat();

            var selfPos = WeaponPos;
            var selfRot = WeaponData.Rotation;
            var targetDir = new BEPUutilities.Vector3(pos.X, pos.Y, 0) - selfPos;
            targetDir.Normalize();
            var curDir = new BEPUutilities.Vector3();
            var upDir = new BEPUutilities.Vector3(0, 1, 0);
            BEPUutilities.Quaternion.Transform(ref upDir, ref selfRot, out curDir);
            var angle = BEPUutilities.Vector3.Angle(curDir, targetDir);
            var crossAxis = BEPUutilities.Vector3.Cross(curDir, targetDir);
            var targetAngle = BEPUutilities.Vector3.Angle(new BEPUutilities.Vector3(0, 1, 0), targetDir);
            var targetCrossAxis = BEPUutilities.Vector3.Cross(new BEPUutilities.Vector3(0, 1, 0), targetDir);
            var angleDifference = crossAxis.Z > 0 ? angle : -angle;
             targetAngle = targetCrossAxis.Z > 0 ? targetAngle : -targetAngle;

            var differenceNormalize = angleDifference / Fix64.Abs(angleDifference);
            var changeAngle = (differenceNormalize * SystemModule.Instance.LogicDelta * WeaponData.Cfg.TurnSpeed);
            if (Fix64.Abs(changeAngle) > Fix64.Abs(angle))
                WeaponData.Angle  = targetAngle;
            else
                WeaponData.Angle += changeAngle;

            m_WeaponView.transform.rotation = UnityEngine.Quaternion.AngleAxis(WeaponData.Angle.ToFloat(), new UnityEngine.Vector3(0, 0, 1));
        }
    }
}
